﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;

using Supremacy.Resources;
using Supremacy.Text;

namespace SupremacyEditor
{
    /// <summary>
    /// Interaction logic for LocalizedTextEditor.xaml
    /// </summary>
    public partial class LocalizedTextEditor
    {
        private static readonly DependencyProperty TextProperty;
        
        public static readonly DependencyProperty AcceptsReturnProperty;
        public static readonly DependencyProperty TextWrappingProperty;
        public static readonly DependencyProperty VerticalScrollBarVisibilityProperty;
        public static readonly DependencyProperty LocalTextProperty;
        public static readonly DependencyProperty PropertyNameProperty;

        static LocalizedTextEditor()
        {
            TextProperty = TextBox.TextProperty.AddOwner(typeof(LocalizedTextEditor));
            AcceptsReturnProperty = TextBoxBase.AcceptsReturnProperty.AddOwner(typeof(LocalizedTextEditor));
            TextWrappingProperty = TextBox.TextWrappingProperty.AddOwner(typeof(LocalizedTextEditor));
            VerticalScrollBarVisibilityProperty = TextBoxBase.VerticalScrollBarVisibilityProperty.AddOwner(
                typeof(LocalizedTextEditor),
                new FrameworkPropertyMetadata(ScrollBarVisibility.Auto));

            PropertyNameProperty = DependencyProperty.Register(
                "PropertyName",
                typeof(string),
                typeof(LocalizedTextEditor),
                new FrameworkPropertyMetadata(OnPropertyNameChanged));

            LocalTextProperty = DependencyProperty.Register(
                "LocalText",
                typeof(string),
                typeof(LocalizedTextEditor),
                new FrameworkPropertyMetadata(
                    string.Empty, 
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
        }

        private void UpdateLocalText()
        {
            var entries = this.DataContext as IEnumerable;
            if (entries == null)
                return;

            var culture = CultureInfo.CurrentCulture;
            ILocalizedTextDatabaseEntry localizedEntry;

            // ReSharper disable AccessToModifiedClosure

            do
            {
                localizedEntry = entries
                    .OfType<ILocalizedTextDatabaseEntry>()
                    .FirstOrDefault(o => string.Equals(o.Language, culture.Name, StringComparison.OrdinalIgnoreCase));
                if (localizedEntry != null)
                    break;
                culture = culture.Parent;
            }
            while (!culture.IsNeutralCulture && (culture.Parent != null) && (culture.Parent != culture));

            culture = ResourceManager.NeutralCulture;

            do
            {
                localizedEntry = entries
                    .OfType<ILocalizedTextDatabaseEntry>()
                    .FirstOrDefault(o => string.Equals(o.Language, culture.Name, StringComparison.OrdinalIgnoreCase));
                if (localizedEntry != null)
                    break;
                culture = culture.Parent;
            }
            while (!culture.IsNeutralCulture && (culture.Parent != null) && (culture.Parent != culture));

            // ReSharper restire AccessToModifiedClosure

            if (localizedEntry == null)
                return;

            SetBinding(
                LocalTextProperty,
                new Binding(this.PropertyName)
                {
                    Source = localizedEntry,
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
        }

        private static void OnPropertyNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var editor = (LocalizedTextEditor)d;
            editor.SetBinding(
                TextProperty,
                new Binding(editor.PropertyName)
                {
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
            editor.UpdateLocalText();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        protected string LocalText
        {
            get { return (string)GetValue(LocalTextProperty); }
            set { SetValue(LocalTextProperty, value); }
        }

        public bool AcceptsReturn
        {
            get { return (bool)GetValue(AcceptsReturnProperty); }
            set { SetValue(AcceptsReturnProperty, value); }
        }

        public TextWrapping TextWrapping
        {
            get { return (TextWrapping)GetValue(TextWrappingProperty); }
            set { SetValue(TextWrappingProperty, value); }
        }

        public ScrollBarVisibility VerticalScrollBarVisibility
        {
            get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); }
            set { SetValue(VerticalScrollBarVisibilityProperty, value); }
        }

        public string PropertyName
        {
            get { return (string)GetValue(PropertyNameProperty); }
            set { SetValue(PropertyNameProperty, value); }
        }

        public LocalizedTextEditor()
        {
            InitializeComponent();

            this.EntryText.SetBinding(
                TextBox.TextProperty,
                new Binding
                {
                    Source = this,
                    Path = new PropertyPath(TextProperty),
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });

            this.DataContextChanged += OnDataContextChanged;
        }

        private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var oldValue = e.OldValue as INotifyCollectionChanged;
            if (oldValue != null)
                oldValue.CollectionChanged -= OnEntriesCollectionChanged;

            var newValue = e.NewValue as INotifyCollectionChanged;
            if (newValue != null)
                newValue.CollectionChanged += OnEntriesCollectionChanged;

            UpdateLocalText();
        }

        private void OnEntriesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UpdateLocalText();
        }

        private void AcceptButton_Click(object sender, RoutedEventArgs e)
        {
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}
